﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using UnityEngine;
using zerogc;

public class hotfixin : MonoBehaviour
{
    ILBridge bridge;
    // Use this for initialization
    void Start()
    {

        ILBridge.logCallback += (log, level) =>
        {
            infos.Add(log);
            if (level == ILBridge.LogLevel.Warn)
            {
                UnityEngine.Debug.LogWarning(log);
            }
            else if (level == ILBridge.LogLevel.Info)
            {
                UnityEngine.Debug.Log(log);
            }
            else if (level == ILBridge.LogLevel.Err)
            {
                UnityEngine.Debug.LogError(log);
            }
        };
        LoadDLL();
    }

    void CloseDLL()
    {
        infos.Clear();
        bridge.CPPDLL_Free();
        bridge = null;
    }
    void LoadDLL()
    {
        infos.Clear();

        //测试 dlopen on android\
        IntPtr runmod = libShell.GetRuntimeModule();
        ILBridge.Log("runmod=" + runmod.ToString("X16"));

        ILBridge.Log("gogogo.");
#if UNITY_EDITOR
        var dllpath = Application.streamingAssetsPath + "\\hotcpp\\windows\\" + "cppscript_windows.dll";
#elif UNITY_ANDROID
        var dllpath = "libcppscript_android.so";
#endif
        bridge = new ILBridge();
        var b = bridge.CPPDLL_Load(dllpath);
        if (!b)
        {
            infos.Add("加载失败");
            bridge = null;
        }
        else
        {
            zerogc.zerogctool.Init(bridge);
            ZeroGCString g = new ZeroGCString();
            ILBridge.Log("zerogc init.");
            StringTool.Free(g);
            ILBridge.Log("zerogc free.");

            ZeroGCString s1 = ZeroGCString.New("hello 123.");
            ILBridge.Log(s1.GetStringObject());
            s1.Free();
        }
    }
    // Update is called once per frame
    void Update()
    {
        if (bridge != null)
            bridge.CPPDLL_CallUpdate();
    }
    List<string> infos = new List<string>();
    void OnGUI()
    {
        GUIUtility.ScaleAroundPivot(new Vector2(3, 3), Vector2.zero);
        GUILayout.BeginHorizontal();
        if (GUILayout.Button("Close DLL", GUILayout.Width(100)))
        {
            CloseDLL();
        }
        if (GUILayout.Button("Load DLL", GUILayout.Width(100)))
        {
            LoadDLL();
        }
        GUILayout.EndHorizontal();
        if (GUILayout.Button("Test ICALL", GUILayout.Width(100)))
        {
            infos.Clear();

            ZeroGCString g = new ZeroGCString();
            ILBridge.Log("zerogc init.");
            StringTool.Free(g);
            ILBridge.Log("zerogc free.");

        }
        if (GUILayout.Button("CPPDLL_DoTest Low"))
        {
            infos.Clear();

            bridge.CPPDLL_Event(0, 0, IntPtr.Zero);
            bridge.CPPDLL_Event(0, 1, IntPtr.Zero);
            bridge.CPPDLL_Event(0, 2, IntPtr.Zero);
            bridge.CPPDLL_Event(0, 3, IntPtr.Zero);
        }
        if (GUILayout.Button("CPPDLL_DoTest High"))
        {
            infos.Clear();

            TestClass t = new TestClass();
            ILBridge.Log("注入之前 tt=" + t.tt());
            bridge.CPPDLL_Event(0, 4, IntPtr.Zero);
            ILBridge.Log("注入之后 tt=" + t.tt());

        }

        if (GUILayout.Button("Test ZeroGC"))
        {
            infos.Clear();
            ILBridge.Log("001");
            ZeroGCString s1 = ZeroGCString.New("hello 123.");
            ILBridge.Log("002");

            for (var i = 0; i < 10000; i++)
            {
                if (i < 10)
                {
                    ILBridge.Log("003");

                    //unsafe String ，unsafe string 限制 2048个字符，超过会被截断
                    string v1 = StringTool.GetStringBuffer(s1);

                    //要丢进infos 的 array，不要用unsafe string，他会变的
                    infos.Add("unsafe+" + v1);
                    s1.AppendString("xx");
                    string v2 = StringTool.GetStringBuffer(s1);
                    //unsafe 特性，内部永远是同一个，获取v2，其实v1 和 v2 根本是同一个

                    infos.Add("unsafe+" + v1);//获取v2会导致v1也变了

                    infos.Add("safe+" + StringTool.GetStringBuffer(s1));
                }
                s1.AppendString("_");
                s1.AppendInt32(i);
            }
            ILBridge.Log("004");

            UnityEngine.Debug.Log("ZeroGC str=" + StringTool.GetStringBuffer(s1));
            s1.Free();
        }
        if (GUILayout.Button("CPPDLL_DoTest Error 102"))
        {
            infos.Clear();

            bridge.CPPDLL_Event(0, 102, IntPtr.Zero);
        }
        if (GUILayout.Button("CPPDLL_DoTest Error 103"))
        {
            infos.Clear();

            bridge.CPPDLL_Event(0, 103, IntPtr.Zero);
        }
        if (GUILayout.Button("CPPDLL_DoTest Error 2"))
        {
            infos.Clear();

            bridge.CPPDLL_Event(2, 103, IntPtr.Zero);
        }

        if (GUILayout.Button("CPPDLL_DoTest 201 field"))
        {
            infos.Clear();

            bridge.CPPDLL_Event(0, 201, IntPtr.Zero);
        }
        foreach (var info in infos)
        {
            GUILayout.Label(info);
        }
    }
}
